
package ubo.master1.jeupoker.ia;

import ubo.master1.jeupoker.gui.LaCart;
import java.util.List;
import java.util.Set;

/**
 * Le joueur
 * 
 */

public class Joueur {
    
    /** Le nom du joueur. */
    private final String name;
    
    /** Type du client reponsable de l'action (robot ou utilisateur humain) */
    private final GenreJoueur client;
    
    /** UneMain  */
    private final UneMain hand;
    
    /** Somme d'artent actuelle . */
    private int cash;
    
    /** Voir si le joueur à les carte a sa diposition. */
    private boolean hasCards;

    /** La mise actuelle. */
    private int bet;
    
    /** La somme de la mise dans le tour courant. */
    private int raises;
    
    /** Le somme du Pot. */
    private int allInPot;
    
    /** La dernier actions. */
    private LesActions action;
    
    /** La dernier somme de la mise increnté. */
    private int betIncrement;

    /**
     * Constructeur.
     * 
     * @param name
     *            Le nom du joueur.
     * @param cash
     *            La somme initial de l'utilisateur.
     * @param client
     *            Type du client.
     */
    public Joueur(String name, int cash, GenreJoueur client) {
        this.name = name;
        this.cash = cash;
        this.client = client;

        hand = new UneMain();

        resetHand();
    }
    
    /**
     * Retourner le client.
     * 
     * @return Le type du client
     */
    public GenreJoueur getClient() {
        return client;
    }
    
    /**
     * Préparer une autre main pour un utilisateur.
     */
    public void resetHand() {
        hand.removeAllCards();
        hasCards = false;
        resetBet();
    }
    
    /**
     * Initialiser les action de l'utilisateur.
     */
    public void resetBet() {
        bet = 0;
        action = null;
        raises = 0;
        allInPot = 0;
        betIncrement = 0;
    }
    
    /**
     * Définir les cartes cachées .
     */
    public void setCards(List<LaCart> cards) {
        hand.removeAllCards();
        if (cards == null) {
            hasCards = false;
        } else {
            if (cards.size() == 2) {
                hand.addCards(cards);
                hasCards = true;
              //  System.out.format("[CHEAT] %s's cards:\t%s\n", name, hand);
            } else {
                throw new IllegalArgumentException("Numero de carte invalide");
            }
        }
    }
    
	/**
	 * Véfifier si le joueur a ces cartes .
	 * 
	 * @return True si les deux carte sont distribué False sinon.
	 */
    public boolean hasCards() {
        return hasCards;
    }
    
    /**
     * Retourne le nom du joueur.
     *
     * @return Le nom.
     */
    public String getName() {
        return name;
    }
    
    /**
     * Retourner la somme actuel d'un joueur.
     *
     * @return le cash.
     */
    public int getCash() {
        return cash;
    }
    
    /**
     * Véfifier si le joueur est à sec.
     *
     * @return True si le joueur n'a plus d'argent , False sinon.
     */
    public boolean isBroke() {
        return (cash == 0);
    }
    
    /**
     * Retourner la somme de la mise actuel .
     *
     * @return The current bet.
     */
    public int getBet() {
        return bet;
    }
    
    /**
     * Retourner la somme des mise effectué par l'utilisateur dans un tour 
     * 
     * @return Le total des mis dans le tour.
     */
    public int getRaises() {
        return raises;
    }
    
    /**
     * Retourner l'action du joueur .
     *
     * @return  l'action efectué
     */
    public LesActions getAction() {
        return action;
    }
    
    /**
     * Retourner la dernier mise incrémenté.
     * 
     * @return la mise incrémenté.
     */
    public int getBetIncrement() {
        return betIncrement;
    }
    
    /**
     * Retourne la main d'un joueur.
     *
     * @return la main .
     */
    public UneMain getHand() {
        return hand;
    }
    
    /**
     * Retourner les cartes caché.
     *
     * @return les cartes caché.
     */
    public LaCart[] getCards() {
        return hand.getCards();
    }
    
    /**
     * miser le  small blind.
     * 
     * @param blind
     *            le small blind.
     */
    public void postSmallBlind(int blind) {
        action = LesActions.SMALL_BLIND;
        cash -= blind;
        bet += blind;
    }
    
    /**
     * Miser le big blinds.
     * 
     * @param blind
     *            Le big blind.
     */
    public void postBigBlind(int blind) {
        action = LesActions.BIG_BLIND;
        cash -= blind;
        bet += blind;
    }
    
    /**
     * Retourne la somme total de la mise effectué par le joueur sur le pot.
     *  
     * @return mise du pot.
     */
    public int getAllInPot() {
        return allInPot;
    }
    
    /**
     * Definir la somme total de la mise effectué par le joueur sur le pot.
     * 
     * @param allInPot
     *            mise du pot.
     */
    public void setInAllPot(int allInPot) {
        this.allInPot = allInPot;
    }
    
	/**
	 * Demander au joueur d'effectuer une action et la retouner 
	 * 
	 * Détérminer les actions d'un utilisateur avec la classe GenreJoueur.
	 * 
	 * @param actions
	 *            L'action.
	 * @param minBet
	 *            la mise minimal.
	 * @param currentBet
	 *            La mise actuel.
	 * 
	 * @return L'action séléctionné par le joueur .
	 */
    public LesActions act(Set<LesActions> actions, int minBet, int currentBet) {
        action = client.act(actions);
        switch (action) {
            case CHECK:
                break;
            case CALL:
                betIncrement = currentBet - bet;
                if (betIncrement > cash) {
                    //TODO: All-in with partial Call.
                    betIncrement = cash;
                }
                cash -= betIncrement;
                bet += betIncrement;
                break;
            case BET:
                betIncrement = minBet;
                if (betIncrement >= cash) {
                    //TODO: All-in with partial Bet.
                    betIncrement = cash;
                }
                cash -= betIncrement;
                bet += betIncrement;
                raises++;
                break;
            case RAISE:
                currentBet += minBet;
                betIncrement = currentBet - bet;
                cash -= betIncrement;
                bet += betIncrement;
                raises++;
                break;
            case FOLD:
                hand.removeAllCards();
                break;
        }
        return action;
    }
    
    /**
     * Ganger le  pot.
     * 
     * @param pot
     *            le pot.
     */
    public void win(int pot) {
        cash += pot;
    }
    
    /**
     * Retouner le clone du joueur.
     * 
     * @return Le clone du joueur.
     */
    public Joueur publicClone() {
        Joueur clone = new Joueur(name, cash, null);
        clone.hasCards = hasCards;
        clone.bet = bet;
        clone.raises = raises;
        clone.action = action;
        return clone;
    }
    
    /*
     * (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return name;
    }
    
}
